﻿namespace Yom.Template
{
    using System;
    using System.Text.RegularExpressions;
    using System.IO;
    using Yom.Common;
    using Yom.Template.Model;

    public class SkinExec
    {
        private string _SkinName;
        private readonly string IncPat = @"(<!--\s*INCLUDE\s+(?<INCLUDE>.*?)\s*-->)";
        private readonly string[] RexPat = new string[] { @"(<!--\s*(?<RUN>ELSE|ENDIF|END|ELSEIF|IF|LOOP)\s*(?<EXE>.*?)\s*-->)", "({Lan\\[\\\"(?<LAN>[a-zA-Z0-9]+)\\\"\\]\\})", @"({(?<VAL>[a-zA-Z0-9_.]+)\})" };

        private string GetSkinText(string strFileName)
        {
            string path = Path.Combine(Path.Combine(Factory.RootPath, string.Format(@"Themes\{0}\{1}", SiteLoad.Scheme.Theme, this._SkinName)), strFileName);

            if (!File.Exists(path))
                path = Path.Combine(Path.Combine(Factory.RootPath, @"Themes\Default"), strFileName);

            return File.ReadAllText(path);
        }

        private SkinTree<SkinNode> Parse(string strSkinText)
        {
            SkinTree<SkinNode> tree = new SkinTree<SkinNode>();
            Regex regex = new Regex(string.Join("|", this.RexPat), RegexOptions.Singleline | RegexOptions.IgnoreCase);
            SkinTreeNode<SkinNode> parent = tree;
            int startIndex = 0;

            foreach (Match m in regex.Matches(strSkinText))
            {
                string run = m.Groups["RUN"].Value.ToUpper();
                string exe = m.Groups["EXE"].Value;
                string lan = m.Groups["LAN"].Value;
                string val = m.Groups["VAL"].Value;
                int index = m.Index;

                if (index > startIndex)
                    parent.AddChild(new TxtSkinNode(strSkinText.Substring(startIndex, index - startIndex)));

                if (run.Length > 0)
                {
                    if (run == "IF")
                        parent = parent.AddChild(new ConSkinNode(exe));
                    else if (run == "LOOP")
                        parent = parent.AddChild(new TblSkinNode(exe));
                    else if (run == "END")
                        parent = parent.Parent;
                    else if (run == "ENDIF")
                        parent = parent.Parent;
                    else if (run == "ELSE")
                    {
                        if (!(parent.Content is ConSkinNode))
                            throw new Exception("无效的 ELSE 模块");

                        string str = string.Format("!{0}", parent.Content.Value);
                        parent = parent.Parent;
                        parent = parent.AddChild(new ConSkinNode(str));
                    }
                }

                if (lan.Length > 0)
                    parent.AddChild(new LanSkinNode(lan));

                if (val.Length > 0)
                    parent.AddChild(new VarSkinNode(val));

                startIndex = m.Index + m.Length;
            }

            if (startIndex < (strSkinText.Length - 1))
                parent.AddChild(new TxtSkinNode(strSkinText.Substring(startIndex)));

            return tree;
        }

        public SkinTree<SkinNode> Parse(string strSkinName, string strFileName)
        {
            this._SkinName = strSkinName;
            string SkinText = this.GetSkinText(strFileName);
            MatchEvaluator evaluator = new MatchEvaluator(this.RunParseHanlder);
            SkinText = Regex.Replace(SkinText, this.IncPat, evaluator, RegexOptions.IgnoreCase);

            return this.Parse(SkinText);
        }

        private string RunParseHanlder(Match token)
        {
            string str = token.Groups["INCLUDE"].Value;

            if (!string.IsNullOrEmpty(str))
                return this.GetSkinText(str);

            return string.Empty;
        }
    }
}